package com.njcb.ams.store.esbmodule;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import com.njcb.ams.pojo.enumvalue.TransStatusCode;
import com.njcb.ams.support.exception.ExceptionWriter;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.transport.http.AbstractHTTPDestination;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.njcb.ams.repository.entity.SysTradeLog;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.support.comm.SequenceService;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.support.exception.SystemException;
import com.njcb.ams.support.trade.TradeUtil;
import com.njcb.ams.util.AmsBeanUtils;
import com.njcb.ams.util.AmsDateUtils;
import com.njcb.ams.util.AmsUtils;
import com.njcb.ams.util.SysInfoUtils;
import com.thoughtworks.xstream.XStream;

/**
 * WebService服务端切面类 使用ASPECTJ类代理 处理ESB规范下的公共处理
 *
 * @author liuyanlong
 */
@Component
@Aspect
@Lazy(false)
@Order(0)
public class WebServiceAspect {
    private static final Logger logger = LoggerFactory.getLogger(WebServiceAspect.class);
    private static XStream xStream = new XStream();

    @SuppressWarnings("unchecked")
    @Around(value = "@within(com.njcb.ams.store.esbmodule.annotation.EsbService) && @args(..)")
    public Object aroundMethod(ProceedingJoinPoint pjd) throws Throwable {
        Object[] objects = pjd.getArgs();
        MethodSignature methodSignature = (MethodSignature) pjd.getSignature();
        if (logger.isInfoEnabled()) {
            Message cxfmessage = PhaseInterceptorChain.getCurrentMessage();
            HttpServletRequest request = (HttpServletRequest) cxfmessage.get(AbstractHTTPDestination.HTTP_REQUEST);
            logger.info("\n请求方地址{}\n请求报文\n{}", request.getRemoteAddr(), xStream.toXML(objects[0]));
        }
        //请求报文头映射对象
        SysHeadBean reqSysHeadBean = getReqSysHeadBean(objects);
        //返回报文头映射对象
        SysHeadBean rspSysHeadBean = initRspSysHeadByReq(reqSysHeadBean);
        //响应报文头
        Object rspSysHeadType = null;
        //获取响应报文头函数
        Method getRspSysHeadMethod = methodSignature.getReturnType().getMethod("getRspSysHead");
        // 执行 实现类
        Object result = null;
        try {
            result = pjd.proceed();
            if (null != result) {
                rspSysHeadType = getRspSysHeadMethod.invoke(result);
            }
            if (null != rspSysHeadType) {
                AmsBeanUtils.copyProperties(rspSysHeadBean, rspSysHeadType);
            }
        } catch (Throwable error) {
            rspSysHeadBean.setTransStatus(TransStatusCode.FAIL.getCode());
            if (null != error.getCause()) {
                error = error.getCause();
            }
            if (error instanceof SystemException) {
                SystemException sysError = (SystemException) error;
                rspSysHeadBean.setRetCode(sysError.getErrorCode());
            }
            rspSysHeadBean.setRetMsg(AmsUtils.isNotNull(error.getMessage()) ? error.getMessage() : error.getClass().getSimpleName());
            ExceptionWriter.writeLog(rspSysHeadBean.getRetCode(), rspSysHeadBean.retMsg, error);
        } finally {
            rspSysHeadBean = getRspSysHeadBean(rspSysHeadBean);
            //如果返回报文头为空,则创建对象
            if (null == rspSysHeadType) {
                rspSysHeadType = getRspSysHeadMethod.getReturnType().newInstance();
            }
            //支持设置返回消息
            if (AmsUtils.isNotNull(EsbHeadUtil.getRetMsg())) {
                rspSysHeadBean.setRetMsg(EsbHeadUtil.getRetMsg());
            }
            AmsBeanUtils.copyProperties(rspSysHeadType, rspSysHeadBean);
            if (null == result) {
                //如果为空，反射创建对象
                result = methodSignature.getReturnType().newInstance();
            }
            Method setRspSysHeadMethod = null;
            Method[] methodArray = result.getClass().getDeclaredMethods();
            for (Method tmpMethod : methodArray) {
                if ("setRspSysHead".equals(tmpMethod.getName())) {
                    setRspSysHeadMethod = tmpMethod;
                }
            }
            setRspSysHeadMethod.invoke(result, rspSysHeadType);
            DataBus.remove();
            logger.info("\n返回报文\n{}", xStream.toXML(result));
        }
        return result;
    }

    private SysHeadBean getRspSysHeadBean(SysHeadBean rspSysHeadBean) {
        // 系统编码
        rspSysHeadBean.setRespSysID(SysInfoUtils.getSysId());
        SysTradeLog tradeLog = DataBus.getAttribute(SysBaseDefine.GLOBALINFO_SYSTRADELOG, SysTradeLog.class);
        if (AmsUtils.isNull(rspSysHeadBean.getTransStatus())) {
            //默认成功
            rspSysHeadBean.setTransStatus(TransStatusCode.SUCC.getCode());
            rspSysHeadBean.setRetCode(SysBaseDefine.TRANS_RET_CODE_DEFAULT);
            rspSysHeadBean.setRetMsg(SysBaseDefine.TRANS_RET_MSG_DEFAULT);
        }
        if (null != tradeLog && AmsUtils.isNull(rspSysHeadBean.getRetCode())) {
            rspSysHeadBean.setRetCode(tradeLog.getRetCode());
        }
        if (null != tradeLog && AmsUtils.isNull(rspSysHeadBean.getRetMsg())) {
            rspSysHeadBean.setRetMsg(tradeLog.getRetMsg());
        }
        return rspSysHeadBean;
    }

    /**
     * 方法功能描述：获取请求Bean
     *
     * @param objects
     * @return
     * @throws Exception
     */
    private SysHeadBean getReqSysHeadBean(Object[] objects) throws Exception {
        Class<? extends Object> reqClass = objects[0].getClass();
        // 获取方法报文头ReqSysHeadType
        Method getReqSysHeadMethod = reqClass.getMethod("getReqSysHead");
        // 获取报文头ReqSysHeadType
        Object reqSysHeadType = getReqSysHeadMethod.invoke(objects[0]);
        if (null == reqSysHeadType) {
            reqSysHeadType = getReqSysHeadMethod.getReturnType().newInstance();
        }
        SysHeadBean reqSysHeadBean = new SysHeadBean();
        AmsBeanUtils.copyProperties(reqSysHeadBean, reqSysHeadType);

        // 请求流水放入数据总线
        EsbHeadUtil.setGlobalSeq(reqSysHeadBean.getGlobalSeq());
        EsbHeadUtil.setSrcSysHead(reqSysHeadBean);
        TradeUtil.setGlobalSeq(reqSysHeadBean.getGlobalSeq());
        TradeUtil.setReqSeq(reqSysHeadBean.getReqSeq());
        return reqSysHeadBean;
    }


    private SysHeadBean initRspSysHeadByReq(SysHeadBean reqSysHeadType) {
        SysHeadBean rspSysHeadType = new SysHeadBean();
        rspSysHeadType.setPkgLength(reqSysHeadType.getPkgLength());
        rspSysHeadType.setServiceID(reqSysHeadType.getServiceID());
        rspSysHeadType.setChannelID(reqSysHeadType.getChannelID());
        rspSysHeadType.setLegOrgID(reqSysHeadType.getLegOrgID());
        rspSysHeadType.setReqDate(reqSysHeadType.getReqDate());
        rspSysHeadType.setReqTime(reqSysHeadType.getReqTime());
        rspSysHeadType.setVersion(reqSysHeadType.getVersion());
        rspSysHeadType.setReqSysID(reqSysHeadType.getReqSysID());
        rspSysHeadType.setDomainRef(reqSysHeadType.getDomainRef());
        rspSysHeadType.setSvcScn(reqSysHeadType.getSvcScn());
        rspSysHeadType.setTmlCd(reqSysHeadType.getTmlCd());
        rspSysHeadType.setAcceptLang(reqSysHeadType.getAcceptLang());
        rspSysHeadType.setGlobalSeq(reqSysHeadType.getGlobalSeq());
        rspSysHeadType.setOrgSysID(reqSysHeadType.getOrgSysID());
        rspSysHeadType.setRespSeq(SequenceService.getEsbSeq());
        rspSysHeadType.setReqSeq(reqSysHeadType.getReqSeq());
        rspSysHeadType.setRespDate(AmsDateUtils.getCurrentDate8());
        rspSysHeadType.setRespTime(AmsDateUtils.getCurrentTime6());
        return rspSysHeadType;
    }
}
